package mh.map.render;

import static mh.entity.EnumState.INTACT;
import static mh.entity.EnumState.LOCKED;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glRotated;
import static org.lwjgl.opengl.GL11.glTexCoord2d;
import static org.lwjgl.opengl.GL11.glTranslated;
import static org.lwjgl.opengl.GL11.glVertex2d;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;

import mh.entity.EnumPosition;
import mh.entity.EnumState;
import mh.entity.object.EntityItem;
import mh.util.Pair;

/**
 * Extends the basic render in order to correctly render an item.<br>
 * Common fields are defined in the extended <code>Render</code> class.
 * 
 * @author Gianmarco Laggia
 * @author Alberto D'Este
 * 
 */
public class RenderItem extends Render {

	public RenderItem(BufferedImage img, int idFromDB, EnumPosition reg) {
		super(img, idFromDB, reg);
	}

	public RenderItem(RenderItem r, EntityItem e) {
		super(r, e);
	}

	@Override
	public void draw(long delta, double posX, double posY, boolean foreground) {
		// We discard the boolean foreground, the item is drawed in the background.
		if (foreground) {
			return;
		}

		EnumState damageState = this.entity.getDamageState();

		if (!this.statesPosition.containsKey(damageState)) {//textureOffset == null) {
			switch (damageState) {
				case DAMAGED:
					this.drawState(INTACT, posX, posY, delta);
					// todo put some sign of damage on the object
					break;
				case BROKEN:
					this.drawState(INTACT, posX, posY, delta);
					// todo put some sign of breackage on the object
					break;
				case BLASTED:
					this.drawBlasted(INTACT, posX, posY, delta);
					return;
				case BURNED:
					// todo draw the texture blackened for the burning
				case INTACT:
					this.drawState(INTACT, posX, posY, delta);
					break;
				default:
					break;
			}
		} else {
			this.drawState(damageState, posX, posY, delta);
		}
		for (EnumState s : this.entity.getStates()) {
			if (this.statesPosition.containsKey(s) && !s.isDamageState()) {
				this.drawState(s, posX, posY, delta);
			}
		}
	}

	private void drawState(EnumState s, double posX, double posY, long delta) {
		Rectangle textureOffset = this.statesPosition.get(s);
		Pair<Integer, Integer> aData = this.statesRectangleAnimationData.get(textureOffset);
		int frames = aData.getLeft();
		int frameDuration = aData.getRight();

		double verW = textureOffset.getWidth();
		double verH = textureOffset.getHeight();

		// ##################### GENERAL ANIMATION
		if (frames > 1) {
			verW = verW / frames;
		}
		int actualFrame = this.actualStatesFrames.get(s);//e.getFrame(s);

		long lastStep = 0;
		if (this.lastStepStates.get(s) != null) {
			lastStep = this.lastStepStates.get(s);
		}
		lastStep += delta;
		if (lastStep > frameDuration) {
			lastStep = 0;
			if ((actualFrame + 1) == frames) {
				this.actualStatesFrames.put(s, 0);//e.setFrame(s, 0);
			} else {
				this.actualStatesFrames.put(s, actualFrame + 1);//e.setFrame(s, actualFrame + 1);
			}
		}
		this.lastStepStates.put(s, lastStep);
		// ##################### END ANIMATION

		// ###################### FLOAT ANIMATION
		Pair<Double, Double> pair = this.applyFloating(posX, posY, delta);
		posX = pair.getLeft();
		posY = pair.getRight();
		// ###################### END FLOAT ANIMATION

		double posXLeft = ((textureOffset.getX() + (actualFrame * verW)) * this.texture.getWidth()) / this.texture.getImageWidth();
		double posXRight = ((textureOffset.getX() + ((actualFrame + 1) * verW)) * this.texture.getWidth()) / this.texture.getImageWidth();
		double posYTop = (textureOffset.getY() * this.texture.getHeight()) / this.texture.getImageHeight();
		double posYBottom = ((textureOffset.getY() + verH) * this.texture.getHeight()) / this.texture.getImageHeight();

		if (s.isDamageState()) {
			this.drawHealthBar(posX, posY, delta);
		}

		glPushMatrix();
		this.texture.bind();
		glColor3f(1, 1, 1);

		// ##################### LOCKED ANIMATION
		if (this.entity.is(LOCKED)) {
			int rotFrame = this.actualStatesFrames.get(LOCKED);//e.getFrame(LOCKED);
			lastStep = 0;
			if (this.lastStepStates.get(LOCKED) != null) {
				lastStep = this.lastStepStates.get(LOCKED);
			}
			lastStep += delta;
			if (lastStep > frameDuration) {
				lastStep = 0;
				if ((rotFrame + 1) == 12) {
					this.entity.getStates().remove(LOCKED);
					this.actualStatesFrames.put(LOCKED, 0);
					rotFrame = 1;
				} else {
					this.actualStatesFrames.put(LOCKED, rotFrame + 1);//e.setFrame(LOCKED, rotFrame + 1);
				}
			}
			this.lastStepStates.put(LOCKED, lastStep);
			glTranslated(posX + ((32 - verW) / 2) + (verW / 2), posY + ((32 - verH) / 2) + (verH / 2), 0);
			int angle = 0;
			switch (rotFrame) {
				case 0:
				case 4:
				case 8:
					angle = -10;
					break;
				case 1:
				case 5:
				case 9:
					angle = 0;
					break;
				case 2:
				case 6:
				case 10:
					angle = 10;
					break;
				case 3:
				case 7:
				case 11:
					angle = 0;
					break;

			}
			glRotated(angle, 0, 0, 1);
			glTranslated(-verW / 2, -verH / 2, 0);
		} else {
			glTranslated(posX, posY, 0);
		}
		// ##################### END LOCKED ANIMATION

		glBegin(GL_QUADS);
		{
			glTexCoord2d(posXLeft, posYTop);
			glVertex2d(0, 0);
			glTexCoord2d(posXLeft, posYBottom);
			glVertex2d(0, verH);
			glTexCoord2d(posXRight, posYBottom);
			glVertex2d(verW, verH);
			glTexCoord2d(posXRight, posYTop);
			glVertex2d(verW, 0);
		}
		glEnd();
		//		glDisable(GL_TEXTURE_2D);
		//		glColor3f(1, 1, 1);
		//		glBegin(GL_LINES);
		//		{
		//			glVertex2d(0, 0);
		//			glVertex2d(40, 30);
		//		}
		//		glEnd();
		//		glEnable(GL_TEXTURE_2D);
		glPopMatrix();
	}

}
//		glBegin(GL_QUADS);
//		{
//			glTexCoord2d((e.getStates().get(e.getDamageState()) * txW) + x, y);
//			glVertex2d(0, 0);
//			glTexCoord2d((e.getStates().get(e.getDamageState()) * txW) + x, txH + y);
//			glVertex2d(0, textureOffset.getHeight());
//			glTexCoord2d(((e.getStates().get(e.getDamageState()) + 1) * txW) + x, txH + y);
//			glVertex2d(textureOffset.getWidth(), textureOffset.getHeight());
//			glTexCoord2d(((e.getStates().get(e.getDamageState()) + 1) * txW) + x, y);
//			glVertex2d(textureOffset.getWidth(), 0);
//
//		}
//		glEnd();
